package com.chalmers.irc2you.model;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Observer;

import com.chalmers.irc2you.SettingsTab;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

/**
 * A Datahandler that functions as a layer between Connection and the activities
 * 
 * @author Scott
 * 
 */
public class DataHandler {

	private static DataHandler INSTANCE = null;
	private String currentChannel;
	private ChannelList cl = ChannelList.getInstance();
	private Context context;
	private SharedPreferences pref;

	/*
	 * All data som sparas och h�mtas g�r genom DataHandler, direktkontakt med
	 * Connection. Connection snackar med Dh, activities ber DH om messages och
	 * kanaler
	 * 
	 * getAllChannels(ger channellist), getLatestUpdateTime,setLatestUpdatetime,
	 * updateChannel,getChannel(?)
	 */
	private DataHandler(Context context) {
		this.context = context;
		pref = PreferenceManager.getDefaultSharedPreferences(context);
		currentChannel = pref.getString("defaultchannel", "#test");
		loadChannels();
	}

	/**
	 * 
	 * @param context
	 *            The application context
	 * @return Returns an instance of DataHandler
	 */
	public static DataHandler getInstance(Context context) {
		if (INSTANCE == null) {
			INSTANCE = new DataHandler(context);
		}
		return INSTANCE;
	}

	/**
	 * 
	 * @return Returns a list of all channels
	 */
	public LinkedList<Channel> getAllChannels() {
		return cl.getAllChannels();
	}

	/**
	 * 
	 * @return Returns the name of the current channel
	 */
	public String getCurrentChannel() {
		return currentChannel;
	}

	/**
	 * 
	 * @param channel
	 *            The name of the channel
	 * @return The latest time the specified channel was updated
	 */
	public String getLatestUpdateTime(String channel) {
		return cl.getChannel(channel).getUpdate();
	}

	/**
	 * 
	 * @param name
	 *            The name of the Channel
	 * @return Returns the entire channel
	 */
	public Channel getChannel(String name) {
		cl.getChannel(name).setRead(true);
		setCurrentChannel(name);
		return cl.getChannel(name);

	}

	private void setCurrentChannel(String name) {
		this.currentChannel = name;
	}

	/**
	 * Creates an empty channel with a selected observer
	 * 
	 * @param obs
	 *            The observer of this channel
	 * @param name
	 *            The name of the channel
	 * @param placement
	 *            What placement the channel will have
	 */
	public void createChannel(String name, LinkedList<Message> msg) {
		Channel newC = new Channel(name, msg);
		cl.addChannel(newC);
	}

	/**
	 * 
	 * @param channelMap
	 */
	public void createChannel(Channel channel) {
		cl.addChannel(channel);
	}

	/**
	 * Updates a specific channels with new messages
	 * 
	 * @param name
	 *            The name of the channel
	 * @param msgs
	 *            A LinkedList containing the messages
	 * @param time
	 *            The time of this update
	 */
	public void updateChannel(String name, LinkedList<Message> msgs, String time) {
		Channel channel = cl.getChannel(name);
		for (int i = 0; i < msgs.size() - 1; i++) {
			channel.addMessage(msgs.get(i));
		}
		channel.setUpdate(time);
	}

	/**
	 * Updates a channel in it's entirety
	 * @param channel the channel to be updated with the new data inside it.
	 * @return true if there was no important value that was null, false otherwise.
	 */
	public boolean updateChannel(Channel channel) {
		//Check so that neither the name of the channel or the messagelist is null.
		if (!(channel.getName() == null) && !(channel.getMessages() == null)) {
			// if the channel doesn't exist in the channelList, create a new one.
			if (cl.getChannel(channel.getName()) == null) {
				createChannel(channel);
			} else {
				//else update the channel.
				updateChannel(channel.getName(), channel.getMessages(), channel
						.getMessages().getLast().getTimeStamp());
			}
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Load saved channels
	 */
	public void loadChannels() {
		String[] temp = context.fileList();
		int i;
		for (i = 0; i < temp.length - 1; i++) {
			try {
				FileInputStream fis = context.openFileInput(temp[i]);
				ObjectInputStream ois = new ObjectInputStream(fis);
				Channel c = (Channel) ois.readObject();
				cl.addChannel(c);
			} catch (IOException e) {
				System.out.println("IOExeption");

			} catch (ClassNotFoundException e) {
				System.out.println("Classnotfoundexception");
			}
		}

	}

	/**
	 * Save channels and clear ChannelList
	 */
	public void saveChannels() {
		LinkedList<Channel> chnls = cl.getAllChannels();
		int i;
		for (i = 0; i < cl.getAllChannels().size() - 1; i++) {
			try {
				FileOutputStream fos = context.openFileOutput(chnls.get(i)
						.getName(), Context.MODE_PRIVATE);
				ObjectOutputStream oos = new ObjectOutputStream(fos);
				oos.writeObject(chnls.get(i));
				oos.close();
			} catch (FileNotFoundException e) {
				System.out.println("filenotfoundexc");
			} catch (IOException e) {
				System.out.println("IOExeption");
			}
		}
		cl.clearAll();
	}
}
